package com.easygoods.service;

import com.bestvike.stone.core.lang.BeanUtils;
import com.bestvike.stone.core.lang.StringUtils;
import com.bestvike.stone.core.time.DateUtils;
import com.bestvike.stone.spring.exception.AssertUtils;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.page.PageableRequest;
import com.bestvike.stone.spring.page.PageableResponse;
import com.bestvike.stone.spring.service.BaseService;
import com.easygoods.bean.MemberGradeInfo;
import com.easygoods.dao.GradeRightDao;
import com.easygoods.dao.MemberCashRecordDao;
import com.easygoods.dao.MemberInfoDao;
import com.easygoods.dao.MemberPointRecordDao;
import com.easygoods.dao.StoreInfoDao;
import com.easygoods.entity.GradeRight;
import com.easygoods.entity.MemberInfo;
import com.easygoods.entity.StoreInfo;
import com.easygoods.enums.AvatarType;
import com.easygoods.request.AcpMemberRequest;
import com.easygoods.request.ChangeMobileBySmsRequest;
import com.easygoods.response.AcpMemberResponse;
import com.easygoods.response.GradeRightResponse;
import com.easygoods.response.MemberCashResponse;
import com.easygoods.response.MemberInfoResponse;
import com.easygoods.response.PointRecordResponseItem;
import com.easygoods.shiro.auth.UserAuth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * Created by 许崇雷 on 2019-01-08.
 */
@Service
public class MemberService extends BaseService {
    @Autowired
    private StoreInfoDao storeInfoDao;
    @Autowired
    private MemberInfoDao memberInfoDao;
    @Autowired
    private PointService pointService;
    @Autowired
    private MemberCashRecordDao memberCashRecordDao;
    @Autowired
    private MemberPointRecordDao memberPointRecordDao;
    @Autowired
    private GradeRightDao gradeRightDao;
    @Autowired
    private CashService cashService;
    @Autowired
    private CouponService couponService;
    @Autowired
    private SmsService smsService;

    //混淆手机号
    public static String messMobile(String mobile) {
        if (mobile == null)
            return StringUtils.EMPTY;
        int len = mobile.length();
        if (len < 11)
            return "****";
        return mobile.substring(0, 3) + "****" + mobile.substring(len - 4, len);
    }

    //获取当前用户信息,无效抛出异常
    public MemberInfo getMemberInfo() {
        final UserAuth userAuth = this.getAuth();
        Assert.notNull(userAuth, "token can not be empty");
        MemberInfo memberInfo = this.memberInfoDao.selectByPrimaryKey(userAuth.getMemberId());
        if (memberInfo == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的用户");
        return memberInfo;
    }

    //获取指定用户信息,无效抛出异常
    public MemberInfo getMemberInfo(String memberId) {
        Assert.hasText(memberId, "memberId can not be empty");
        MemberInfo memberInfo = this.memberInfoDao.selectByPrimaryKey(memberId);
        if (memberInfo == null) {
            this.log.error("用户不存在 memberId:" + memberId);
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的用户");
        }
        return memberInfo;
    }

    //获取用户 for update
    public MemberInfo getMemberInfoForUpdate(String memberId) {
        Assert.hasText(memberId, "memberId 不能为空");

        Example example = new Example(MemberInfo.class);
        example.createCriteria().andEqualTo(MemberInfo.ID, memberId);
        example.setForUpdate(true);
        MemberInfo memberInfo = this.memberInfoDao.selectOneByExample(example);
        if (memberInfo == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的用户");
        return memberInfo;
    }

    //获取当前用户的 store 信息,无效抛出异常
    public StoreInfo getStoreInfo() {
        final UserAuth userAuth = this.getAuth();
        Assert.notNull(userAuth, "token can not be empty");
        return this.getStoreInfo(userAuth.getMemberId());
    }

    //获取指定用户的 Store,无效抛出异常
    public StoreInfo getStoreInfo(String memberID) {
        Example example = new Example(StoreInfo.class);
        example.createCriteria().andEqualTo(StoreInfo.MEMBER_ID, memberID);
        StoreInfo storeInfo = this.storeInfoDao.selectOneByExample(example);
        if (storeInfo == null)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的用户");
        return storeInfo;
    }

    //获取个人中心
    public MemberInfoResponse getMemberCenter() {
        MemberInfo memberInfo = this.getMemberInfo();
        MemberGradeInfo gradeInfo = this.pointService.computeGrade(memberInfo.getTotalPoint());

        MemberInfoResponse response = BeanUtils.toBean(memberInfo, MemberInfoResponse.class);
        response.setTotalNormalCoupon(this.couponService.sumNormalCoupon(memberInfo.getId()));
        response.setTotalTeamCoupon(BigDecimal.ZERO);//团队代金券
        response.setInviteUnsettledCash(this.cashService.computeInviteUnsettledGoods());//带收益
        //
        response.setGrade(gradeInfo.getGrade());
        response.setGradeName(gradeInfo.getGradeName());
        response.setNextGrade(gradeInfo.getNextGrade());
        response.setNextGradeName(gradeInfo.getNextGradeName());
        response.setPoint(gradeInfo.getPoint());
        response.setPointUpper(gradeInfo.getPointUpper());
        response.setPointLower(gradeInfo.getPointLower());
        return response;
    }

    //统计指定用户邀请了多少人
    public int countInvitedMembers(String memberId) {
        Assert.notNull(memberId, "memberId can not be null");

        final Example example = new Example(MemberInfo.class);
        example.createCriteria().andEqualTo(MemberInfo.REF_MEMBER_ID, memberId);
        return this.memberInfoDao.selectCountByExample(example);
    }

    //查询该用户现金余额列表
    public PageableResponse<MemberCashResponse> getMemberCashList(PageableRequest pageableRequest) {
        final UserAuth userAuth = this.getAuth();
        //获取激励明细列表
        List<MemberCashResponse> memberCashResponseList = this.memberCashRecordDao.getMemberCashList(userAuth.getMemberId(), pageableRequest.toRowBounds());
        return PageableResponse.create(memberCashResponseList);
    }

    //查询该会员邀请的会员
    public PageableResponse<AcpMemberResponse> getAcpMemberList(AcpMemberRequest acpMemberRequest) {
        final UserAuth userAuth = this.getAuth();
        Calendar calendar = DateUtils.nowCalendar();
        calendar.add(Calendar.MONTH, -acpMemberRequest.getMonths());
        Date previousDate = calendar.getTime();
        List<AcpMemberResponse> acpMemberResponseList = this.memberInfoDao.getAcpMemberList(userAuth.getMemberId(), previousDate, acpMemberRequest.toRowBounds());
        return PageableResponse.create(acpMemberResponseList);
    }

    //查询该会员积分记录
    public PageableResponse<PointRecordResponseItem> getPointList(PageableRequest pageableRequest) {
        final UserAuth userAuth = this.getAuth();

        List<PointRecordResponseItem> pointRecordResponseItemList = this.memberPointRecordDao.getMemberPointList(userAuth.getMemberId(), pageableRequest.toRowBounds());
        return PageableResponse.create(pointRecordResponseItemList);
    }

    //查询等级权益
    public List<GradeRightResponse> getGradeRightList(int grade) {
        final Example example = new Example(GradeRight.class);
        example.createCriteria().andEqualTo(GradeRight.GRADE, grade);
        example.orderBy(GradeRight.DISPLAY_ORDER);
        final List<GradeRight> gradeRights = this.gradeRightDao.selectByExample(example);
        return BeanUtils.toList(gradeRights, GradeRightResponse.class);
    }

    //修改用户昵称头像
    public void modifyMemberInfo(String memberId, String nickName, AvatarType avatarType, String avatar) {
        AssertUtils.hasText(memberId, "memberId");

        //不需要更新
        if (StringUtils.isBlank(nickName) && avatarType == null)
            return;

        MemberInfo memberInfo = new MemberInfo();
        memberInfo.setId(memberId);
        if (StringUtils.isNotBlank(nickName)) {
            memberInfo.setNickName(nickName);
        }
        if (avatarType != null) {
            AssertUtils.hasText(avatar, "avatar");
            memberInfo.setAvatarType(avatarType.name());
            memberInfo.setAvatar(avatar);
        }
        memberInfo.beforeUpdate();
        final int updateCount = this.memberInfoDao.updateByPrimaryKeySelective(memberInfo);
        if (updateCount != 1)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "无效的用户");
    }


    //根据短信验证码修改手机号
    @Transactional
    public void changeMobileBySms(ChangeMobileBySmsRequest request) {
        this.smsService.checkChangeMobileSms(request);
        final MemberInfo memberInfo = this.getMemberInfo();
        this.updateMobileCore(memberInfo.getId(), request.getNewMobile());
    }

    //更改支付密码
    private void updateMobileCore(String memberId, String newMobile) {
        final MemberInfo memberInfoUpdate = new MemberInfo();
        memberInfoUpdate.setId(memberId);
        memberInfoUpdate.setMobile(newMobile);
        final int count = this.memberInfoDao.updateByPrimaryKeySelective(memberInfoUpdate);
        if (count != 1)
            throw new BusinessException(ErrorCode.ERROR_SERVER, "修改绑定手机号失败");

        //修改授权中的手机号
        final UserAuth auth = this.getAuth();
        auth.setMobile(newMobile);
        auth.save();
    }
}
